/*
 *  Copyright 2008-2010 www.jrails.org
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.rails.core.model;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.rails.core.db.SQLHelper;
import org.rails.core.db.table.Table;
import org.rails.core.model.attribute.Attribute;
import org.rails.core.resource.ConfigBuilder;
import org.rails.core.resource.ResourceFactory;
import org.rails.core.util.Utils;

import org.apache.log4j.Logger;

@SuppressWarnings("serial")
public abstract class ActiveRecordBase extends HashMap<String, Object> {
	
	protected final static ConfigBuilder config = ResourceFactory.getConfigBuilder();

	protected final Logger logger = Logger.getLogger(this.getClass());

	protected DataSource dataSource;
	
	protected SQLHelper sqlHelper;
	
	protected Table table;

	protected List<String> attributes;

	public ActiveRecordBase(DataSource dataSource) {
		super();
		this.dataSource = dataSource;
		table = new Table(dataSource,this.getClass());
		sqlHelper = new SQLHelper(dataSource);
		attributes = getAttributes();
	}

	public ActiveRecordBase(DataSource dataSource,final Map<String, Object> m) {
		super();
		this.dataSource = dataSource;
		table = new Table(dataSource,this.getClass());
		sqlHelper = new SQLHelper(dataSource);
		attributes = getAttributes();
		this.putAll(m);
	}
	
	public ActiveRecordBase(DataSource dataSource,String tableName){
		super();
		this.dataSource = dataSource;
		table = new Table(dataSource,tableName);
		sqlHelper = new SQLHelper(dataSource);
		attributes = getAttributes();
	}

	public void setId(Object id) {
		this.put(table.getPrimaryKey(), id);
	}

	public Object getId() {
		return this.get(table.getPrimaryKey());
	}

	public List<String> getAttributes() {
		return table.getColumns();	
	}

	public Table getTable() {
		return table;
	}

	public void removeAttribute(String attribute) {
		remove(attribute);
	}

	public void removeId() {
		removeAttribute(table.getPrimaryKey());
	}

	public boolean containsAttribute(String attribute) {
		return containsKey(attribute);
	}

	@Override
	public Object put(String attribute, Object value) {
		final Attribute att = new Attribute((ActiveRecord) this.clone(), attribute);
		try {
			return super.put(attribute, att.parse(value));
		} catch (Exception e) {
			return super.put(attribute, value);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public void putAll(Map m) {
		final List<String> keys = Utils.getKeys(m);
		for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {
			String key = iterator.next();
			put(key, m.get(key));
		}
	}
	
	public DataSource getDataSource() {
		return dataSource;
	}

	public Attribute getAttribute(String attribute) {
		return new Attribute((ActiveRecord) this.clone(), attribute);
	}

	public Integer getInteger(String attribute) {
		return (Integer) get(attribute);
	}

	public Short getShort(String attribute) {
		return (Short) get(attribute);
	}

	public Byte getByte(String attribute) {
		return (Byte) get(attribute);
	}

	public Long getLong(String attribute) {
		return (Long) get(attribute);
	}

	public Float getFloat(String attribute) {
		return (Float) get(attribute);
	}

	public Double getDouble(String attribute) {
		return (Double) get(attribute);
	}
	
	public Boolean getBoolean(String attribute){
		return (Boolean)get(attribute);
	}

	public Timestamp getTimestamp(String attribute) {
		return (Timestamp) get(attribute);
	}
	
	public BigInteger getBigInteger(String attribute) {
		return (BigInteger) get(attribute);
	}
	
	public BigDecimal getBigDecimal(String attribute) {
		return (BigDecimal) get(attribute);
	}

	public String getString(String attribute) {
		if (get(attribute) == null)
			return null;
		else
			return get(attribute).toString();
	}

	public Object get(String attribute) {
		return super.get(attribute);
	}

	public SQLHelper getSqlHelper() {
		return sqlHelper;
	}


}
